import 'dart:io';
import 'dart:math';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
import 'package:video_player/video_player.dart';
import '../../app_files.dart';

typedef DoubleClickAnimationListener = void Function();

class MediaAlbumView extends StatefulWidget {
  final List files;
  final int initialIndex;

  const MediaAlbumView({
    this.files,
    this.initialIndex = 0,
  });

  @override
  _MediaAlbumViewState createState() => _MediaAlbumViewState();
}

class _MediaAlbumViewState extends State<MediaAlbumView>
    with TickerProviderStateMixin {
  int currentIndex;
  Map controllers = {};
  AnimationController _doubleClickAnimationController;
  Animation<double> _doubleClickAnimation;
  DoubleClickAnimationListener _doubleClickAnimationListener;
  List<double> doubleTapScales = <double>[1.0, 2.5];
  GlobalKey<ExtendedImageSlidePageState> slidePageKey =
      GlobalKey<ExtendedImageSlidePageState>();

  @override
  void dispose() {
    _doubleClickAnimationController.dispose();
    for (var items in controllers.values) {
      VideoPlayerController _videoPlayerController = items;
      _videoPlayerController.pause();
      _videoPlayerController.dispose();
    }
    super.dispose();
  }

  @override
  void initState() {
    _doubleClickAnimationController = AnimationController(
        duration: const Duration(milliseconds: 150), vsync: this);
    currentIndex = widget.initialIndex;
    for (var file in widget.files) {
      if (file is AssetEntityFile) {
        if (file.isVideo) {
          VideoPlayerController _videoPlayerController =
              VideoPlayerController.file(file.file);
          controllers[file.fileId] = _videoPlayerController;
        }
      } else {
        String url = file.toString().split('|').first;
        if (url.endsWith('mp4')) {
          VideoPlayerController _videoPlayerController =
              VideoPlayerController.network(NetworkConfig.imageUrl(url));
          controllers[file.toString()] = _videoPlayerController;
        }
      }
    }
    super.initState();
  }

  void onPageChanged(int index) {
    for (var items in controllers.values) {
      VideoPlayerController _videoPlayerController = items;
      _videoPlayerController.pause();
    }

    setState(() {
      currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      body: Stack(
        children: [
          ExtendedImageSlidePage(
            key: slidePageKey,
            slideAxis: SlideAxis.vertical,
            slideType: SlideType.onlyImage,
            child: GestureDetector(
              child: ExtendedImageGesturePageView.builder(
                controller: PageController(initialPage: widget.initialIndex),
                onPageChanged: onPageChanged,
                itemCount: widget.files.length,
                itemBuilder: (BuildContext context, int index) {
                  var file = widget.files[index];
                  Widget body;
                  if (file is AssetEntityFile) {
                    if (file.isVideo) {
                      VideoPlayerController _videoPlayerController =
                          controllers[file.fileId];
                      body = VideoThumbWidget(
                        videoPlayerController: _videoPlayerController,
                        thumbFile: file.thumbFile,
                      );
                    } else {
                      body = ExtendedImage.file(
                        file.file,
                        fit: BoxFit.contain,
                        mode: ExtendedImageMode.gesture,
                        initGestureConfigHandler: (ExtendedImageState state) {
                          return GestureConfig(
                            //you must set inPageView true if you want to use ExtendedImageGesturePageView
                            inPageView: true,
                            initialScale: 1.0,
                            maxScale: 5.0,
                            animationMaxScale: 6.0,
                            initialAlignment: InitialAlignment.center,
                          );
                        },
                        onDoubleTap: (ExtendedImageGestureState state) {
                          ///you can use define pointerDownPosition as you can,
                          ///default value is double tap pointer down postion.
                          final Offset pointerDownPosition =
                              state.pointerDownPosition;
                          final double begin = state.gestureDetails.totalScale;
                          double end;

                          //remove old
                          _doubleClickAnimation
                              ?.removeListener(_doubleClickAnimationListener);

                          //stop pre
                          _doubleClickAnimationController.stop();

                          //reset to use
                          _doubleClickAnimationController.reset();

                          if (begin == doubleTapScales[0]) {
                            end = doubleTapScales[1];
                          } else {
                            end = doubleTapScales[0];
                          }

                          _doubleClickAnimationListener = () {
                            //print(_animation.value);
                            state.handleDoubleTap(
                                scale: _doubleClickAnimation.value,
                                doubleTapPosition: pointerDownPosition);
                          };
                          _doubleClickAnimation =
                              _doubleClickAnimationController
                                  .drive(Tween<double>(begin: begin, end: end));

                          _doubleClickAnimation
                              .addListener(_doubleClickAnimationListener);

                          _doubleClickAnimationController.forward();
                        },
                      );
                    }
                  } else {
                    String url = file.toString().split('|').first;
                    if (url.endsWith('mp4')) {
                      VideoPlayerController _videoPlayerController =
                          controllers[file.toString()];
                      body = VideoThumbWidget(
                        videoPlayerController: _videoPlayerController,
                        thumbUrl: file.toString().split('|').last,
                      );
                    } else {
                      body = ExtendedImage.network(
                        NetworkConfig.imageUrl(file),
                        fit: BoxFit.contain,
                        mode: ExtendedImageMode.gesture,
                        loadStateChanged: (ExtendedImageState state) {
                          if (state.extendedImageLoadState ==
                              LoadState.completed)
                            return RepaintBoundary(
                                child: state.completedWidget);
                          return MyLoadingWidget();
                        },
                        initGestureConfigHandler: (ExtendedImageState state) {
                          return GestureConfig(
                            //you must set inPageView true if you want to use ExtendedImageGesturePageView
                            inPageView: true,
                            initialScale: 1.0,
                            maxScale: 5.0,
                            animationMaxScale: 6.0,
                            initialAlignment: InitialAlignment.center,
                          );
                        },
                        onDoubleTap: (ExtendedImageGestureState state) {
                          ///you can use define pointerDownPosition as you can,
                          ///default value is double tap pointer down postion.
                          final Offset pointerDownPosition =
                              state.pointerDownPosition;
                          final double begin = state.gestureDetails.totalScale;
                          double end;

                          //remove old
                          _doubleClickAnimation
                              ?.removeListener(_doubleClickAnimationListener);

                          //stop pre
                          _doubleClickAnimationController.stop();

                          //reset to use
                          _doubleClickAnimationController.reset();

                          if (begin == doubleTapScales[0]) {
                            end = doubleTapScales[1];
                          } else {
                            end = doubleTapScales[0];
                          }

                          _doubleClickAnimationListener = () {
                            //print(_animation.value);
                            state.handleDoubleTap(
                                scale: _doubleClickAnimation.value,
                                doubleTapPosition: pointerDownPosition);
                          };
                          _doubleClickAnimation =
                              _doubleClickAnimationController
                                  .drive(Tween<double>(begin: begin, end: end));

                          _doubleClickAnimation
                              .addListener(_doubleClickAnimationListener);

                          _doubleClickAnimationController.forward();
                        },
                      );
                    }
                  }
                  return body;
                },
              ),
              onTap: () {
                Navigator.pop(context);
              },
            ),
            slidePageBackgroundHandler: (Offset offset, Size pageSize) {
              // double opacity = offset.dy.abs() / (pageSize.height / 2.0);
              double opacity = offset.distance /
                  (Offset(pageSize.width, pageSize.height).distance / 2.0);
              Color color = const Color(0xff000000)
                  .withOpacity(min(1.0, max(1.0 - opacity, 0.0)));
              return color;
            },
          ),
          Positioned(
            top: 6,
            left: 0,
            right: 20,
            child: InkWell(
              onTap: () => Navigator.pop(context),
              child: SizedBox(
                height: MediaQuery.of(context).padding.top + 80,
                child: Row(
                  children: [
                    MyInkWellWidget(
                      child: Padding(
                        padding: const EdgeInsets.only(left: 12, right: 18),
                        child: Image.asset('images/ic_back_white.png'),
                      ),
                      onTap: () => Navigator.pop(context),
                    ),
                    Text(
                      "${currentIndex + 1}/${widget.files.length}",
                      style: const TextStyle(
                          color: Colors.white,
                          fontSize: 18.0,
                          fontWeight: FontWeight.w600),
                    ),
                    Expanded(child: Container()),
                  ],
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// ignore: must_be_immutable
class VideoThumbWidget extends StatefulWidget {
  final VideoPlayerController videoPlayerController;
  final File thumbFile;
  final String thumbUrl;

  const VideoThumbWidget({
    this.videoPlayerController,
    this.thumbFile,
    this.thumbUrl,
  });

  @override
  _VideoState createState() => _VideoState();
}

class _VideoState extends State<VideoThumbWidget> {
  bool _isInitialized = false;
  bool _isPlaying = false;
  VoidCallback listener;

  @override
  void initState() {
    if (!widget.videoPlayerController.value.initialized) {
      widget.videoPlayerController.initialize().then((value) => setState(() {
            print('initState ${widget.videoPlayerController.dataSource}');
            // _isInitialized = true;
          }));
    }
    listener = () {
      if (widget.videoPlayerController.value.errorDescription != null) {
        CommonUtils.showErrorInfo(context, '播放失败，请重新打开');
        Navigator.pop(context);
      }
      if (!_isInitialized &&
          widget.videoPlayerController.value.duration != null) {
        Future.delayed(Duration(milliseconds: 500))
            .then((value) => setState(() {
                  _isInitialized = true;
                }));
      }
      if (widget.videoPlayerController.value.position ==
              widget.videoPlayerController.value.duration &&
          _isPlaying) {
        _isPlaying = false;
        widget.videoPlayerController.pause();
        widget.videoPlayerController.seekTo(Duration());
        setState(() {});
      }
    };

    widget.videoPlayerController.addListener(listener);

    super.initState();
  }

  @override
  void dispose() {
    widget.videoPlayerController.removeListener(listener);
    super.dispose();
  }

  @override
  void didChangeDependencies() {
    _isInitialized = widget.videoPlayerController.value.initialized;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    if (!_isInitialized) {
      return Stack(
        children: [
          Positioned.fill(child: MyLoadingWidget()),
        ],
      );
    }

    return Stack(
      children: [
        Positioned.fill(
          child: MyInkWellWidget(
            child: VideoPlayer(widget.videoPlayerController),
            onTap: () => setState(() {
              _isPlaying = false;
              widget.videoPlayerController.pause();
            }),
          ),
        ),
        Positioned(
          left: 0,
          right: 0,
          top: 0,
          bottom: 0,
          child: widget.videoPlayerController.value.isPlaying
              ? Container()
              : MyInkWellWidget(
                  child: Image.asset('images/ic_play.png'),
                  onTap: () => setState(() {
                    _isPlaying = true;
                    widget.videoPlayerController.play();
                  }),
                ),
        )
      ],
    );
  }
}
